#ifndef __MBRTU_H__
#define __MBRTU_H__

#include <stdint.h>

#define MBRTU_ERR_NONE 0
#define MBRTU_ERR_ID 1
#define MBRTU_ERR_RLEN 2
#define MBRTU_ERR_CRC 3
#define MBRTU_ERR_FUN 4
#define MBRTU_ERR_ADDR 5

#define ILLEGALFUNCTION 1
#define ILLEGALDATAADDRESS 2
#define ILLEGALDATAVALUE 3
#define SLAVEDEVICEFAILURE 4
#define ACKNOWLEDGE 5
#define SLAVEDEVICEBUSY 6
#define GATEWAYPATHUNAVAILABLE 0xA
#define GATEWAYTARGETDEVICEFAILEDTORESPOND 0xB

typedef int32_t (*pcoil_fun)(uint16_t *a, uint16_t len, uint8_t **p);
typedef int32_t (*preg_fun)(uint16_t *a, uint16_t len, uint16_t **p);
typedef struct
{
    uint8_t id;
    uint8_t inited;
    pcoil_fun coil_callback;
    preg_fun reg_callback;
} mbrtu_type;

extern int32_t mbrtu_init(mbrtu_type *, uint8_t, pcoil_fun, preg_fun);
extern int32_t mbrtu_mainloop(mbrtu_type *p, uint8_t *pr, uint8_t *pt, uint16_t rlen, uint16_t *ptlen);
extern int32_t mbrtu_mainlooptcp(mbrtu_type *p, uint8_t *pr, uint8_t *pt, uint16_t rlen, uint16_t *ptlen);
extern uint16_t mbrtu_crc16(uint8_t *ndata, uint16_t wlength);

/*
demo

mbrtu_type mb;

uint8_t coil[32]; // 256 bits

uint16_t reg[32]; // 32 regs

int32_t coil_fun(uint16_t *a, uint16_t len, uint8_t **p)
{
    if (*a < (sizeof(coil) << 3))
    {
        *p = (uint8_t *)coil;
        if ((*a + len) > (sizeof(coil) << 3))
        {
            return MBRTU_ERR_ADDR;
        }
    }
    else
    {
        return MBRTU_ERR_ADDR;
    }
    return MBRTU_ERR_NONE;
}
int32_t reg_fun(uint16_t *a, uint16_t len, uint16_t **p)
{
    if (*a < (sizeof(reg) >> 1))
    {
        *p = (uint16_t *)reg;
        if ((*a + len) > (sizeof(reg) >> 1))
        {
            return MBRTU_ERR_ADDR;
        }
    }
    else
    {
        return MBRTU_ERR_ADDR;
    }
    return MBRTU_ERR_NONE;
}

void mb_init(void)
{
    mb.id = 1;
    mb.coil_callback = coil_fun;
    mb.reg_callback = reg_fun;
    mb.inited = 1;
}

void mb_process(uint8_t *Buf, uint32_t Len)
{
    // Buf   receive buffer
    // Len   receive byte size
    // UserTxBufferFS send buffer

    uint16_t tlen = 0; // send byte size

    mbrtu_mainloop(&mb, Buf, UserTxBufferFS, Len, &tlen);
    if (tlen)
    {
        // to do send
        // CDC_Transmit_FS(UserTxBufferFS,tlen);
    }
}
*/

#endif
